//
// Created by DELL on 2025/2/13.
//

#ifndef ANY_H
#define ANY_H
#include <iostream>
#include <memory>
#include <typeinfo>

namespace zdotp {

    class Any {
    public:

        Any() = default;
        ~Any() = default;
        Any(Any&&) = default;
        Any& operator=(Any&&) = default;

        Any(const Any&) = delete;
        Any& operator=(const Any&) = delete;

        template<class T>
        Any(T data) : base_(std::make_unique<Derive<T>>(data)) {}

        template<class T>
        T cast() {
            auto* ptr = dynamic_cast<Derive<T>*>(base_.get());
            if (ptr == nullptr) {
                throw std::bad_cast();
            }
            return ptr->data_;
        }

        template<class T>
        T cast() const {
            auto* ptr = dynamic_cast<const Derive<T>*>(base_.get());
            if (ptr == nullptr) {
                throw std::bad_cast();
            }
            return ptr->data_;
        }

    private:

        class Base {
        public:
            virtual ~Base() = default;
        };

        template<class T>
        class Derive : public Base {
        public:
            Derive(T data) : data_(data){}
            T data_;
        };

        std::unique_ptr<Base> base_;
    };
} // zdotp

#endif //ANY_H